import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import java.awt.geom.Line2D;

public class GameWindow extends JFrame implements MouseListener, MouseMotionListener, KeyListener
{
  boolean up,down,left,right,mouseDown;
  int mouseX,mouseY;
  ShipManager shipManager;
  Ship playerShip;
  BufferedImage buffer;
  CheckPhasers checkPhaser;
  static int ships=0;
  

  public void mousePressed (MouseEvent e)
  {
    mouseDown=true;
  }
  
  
  public void mouseReleased (MouseEvent e)
  {
    mouseDown=false;
  }
  
  
  public void mouseClicked (MouseEvent e)
  {
    
  }  
  
  public void mouseEntered (MouseEvent e)
  {
    
  }
  
  public void mouseExited (MouseEvent e)
  {
    
  }
  
  public void mouseMoved(MouseEvent e)
  {
    mouseX = e.getX();
    mouseY = e.getY();
  }
  
  public void mouseDragged(MouseEvent e)
  {
    mouseX = e.getX();
    mouseY = e.getY();
  }
  
  public void keyPressed (KeyEvent e)
  {
    if (e.getKeyCode()==e.VK_LEFT)
      left=true;
    if(e.getKeyCode()==e.VK_RIGHT)
      right=true;
    if(e.getKeyCode()==e.VK_UP)
      up=true;
    if(e.getKeyCode()==e.VK_DOWN)
      down=true;
    
    if (e.getKeyCode()==e.VK_A)
      left=true;
    if(e.getKeyCode()==e.VK_D)
      right=true;
    if(e.getKeyCode()==e.VK_W)
      up=true;
    if(e.getKeyCode()==e.VK_S)
      down=true;
  }
  
  public void keyTyped (KeyEvent e)
  {
    
  }
  
  public void keyReleased (KeyEvent e)
  {
    if (e.getKeyCode()==e.VK_LEFT)
    {
      left=false;
    }
    if(e.getKeyCode()==e.VK_RIGHT)
      right=false;
    if(e.getKeyCode()==e.VK_UP)
      up=false;
    if(e.getKeyCode()==e.VK_DOWN)
      down=false;
    
    if (e.getKeyCode()==e.VK_A)
      left=false;
    if(e.getKeyCode()==e.VK_D)
      right=false;
    if(e.getKeyCode()==e.VK_W)
      up=false;
    if(e.getKeyCode()==e.VK_S)
      down=false;
    
    if(e.getKeyChar()=='r')
    {
      new GameWindow();
      this.dispose();
    }
    
  }
  
  public GameWindow ()
  {
    
    super ("Space Wars");
    addMouseListener (this);
    addMouseMotionListener(this);
    addKeyListener(this);
    setResizable (false);
    setSize (640,480);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    buffer=new BufferedImage(640,480,BufferedImage.TYPE_INT_RGB);
    
    playerShip=new Ship(300,300,Color.red);
    
    
    shipManager= new ShipManager(this);
    shipManager.addShip(playerShip);
    
    shipManager.addShip(new Ship(500+(int)((Math.random()-0.5)*20),200+(int)((Math.random()-0.5)*20),Color.gray));
    shipManager.addShip(new Ship(100+(int)((Math.random()-0.5)*20),200+(int)((Math.random()-0.5)*20),Color.white));
    
    shipManager.addShip(new Ship(50+(int)((Math.random()-0.5)*20),50+(int)((Math.random()-0.5)*20),Color.yellow));
    shipManager.addShip(new Ship(100+(int)((Math.random()-0.5)*20),500+(int)((Math.random()-0.5)*20),Color.green));
    
    shipManager.start();
    for (int i=0;i<ships;i++)
    {
      shipManager.getShips().remove(shipManager.getShips().get(shipManager.getShips().size()-1));
    }
    checkPhaser= new CheckPhasers(this);
    checkPhaser.start();
    
    setVisible(true);
    repaint();
  }
  
  /* DEBUG FOR SHIELD ROTATION */
  // Returns the location of point after rotation about origin
  public Point getRotatedPoint (double originX, double originY, double x, double y, double angle)
  {
    double cost, sint, xr, yr, newX, newY;
    
    cost = Math.cos (angle);
    sint = Math.sin (angle);
    
    xr = x - originX;
    yr = y - originY;
    
    newX = cost * xr - sint * yr;
    newY = sint * xr + cost * yr;
    
    newX += originX;
    newY += originY;
    
    return new Point ((int) newX, (int) newY);
  }
  ////////////////////////*/
  
  public void paint (Graphics g)
  {
    Point topLeft, topRight, bottomRight, bottomLeft;///
    
    controls();
    ArrayList<Ship>ships;
    ArrayList<Phaser>phasers;
    try
    {
      ships= new ArrayList<Ship>(shipManager.getShips());
    }
    catch(Exception e)
    {
      ships=new ArrayList<Ship>();
      System.out.println("No ships avaliable");
    }
    try
    {
      phasers= new ArrayList<Phaser>(checkPhaser.phasers);
    }
    catch (Exception e)
    {
      phasers=new ArrayList<Phaser>();
    }
    Graphics img= buffer.createGraphics();
    Graphics2D img2= (Graphics2D)img;
    img.setColor(Color.black);
    img.fillRect(0,0,640,480);
    for (Ship s:ships)
    {
      Graphics2D shipGfx= (Graphics2D)s.shipBuffer.createGraphics();
      shipGfx.setColor(Color.black);
      shipGfx.fillRect(0,0,50,50);
      shipGfx.rotate((s.angle*-1),17,17);
      shipGfx.setColor(s.color);
      shipGfx.fillRect(5,5,25,25);
      
      
      /* DEBUG FOR SHIELD ROTATION */
      double w = s.shipRect.getWidth();
      double h = s.shipRect.getHeight();
      
      // Gets the coordinates of ship after rotation
      topLeft=getRotatedPoint(s.x+w/2,s.y+h/2, s.x, s.y, -s.angle);
      topRight=getRotatedPoint(s.x+w/2,s.y+h/2, s.x+w, s.y, -s.angle);
      bottomLeft=getRotatedPoint(s.x+w/2,s.y+h/2, s.x, s.y+h, -s.angle);
      bottomRight=getRotatedPoint(s.x+w/2,s.y+h/2, s.x+w, s.y+h, -s.angle);
             
      img.setColor(Color.white);
      img.drawString("HP: "+s.hp+" "+s.shields[0]+" "+s.shields[1]+" "+s.shields[2]+" "+s.shields[3],s.coords().x,s.coords().y);
      img.drawString("Battery: "+s.battery,s.coords().x,s.coords().y-12);
      img.drawString("",s.coords().x,s.coords().y-12);
      
     
      
      img.drawImage(s.shipBuffer,s.coords().x,s.coords().y,null);
      
      img.setColor(s.color);
      //img.drawRect(s.coords().x,s.coords().y,(int)s.shipRect.getHeight(),(int)s.shipRect.getWidth());
      
      
      
      
      
     /* img.setColor(Color.green);
      img.drawOval ((int)s.x+18,(int)s.y+18,3,3);
      img.drawOval ((int)topLeft.getX(), (int)topLeft.getY(), 2, 2);
      img.drawOval ((int)topRight.getX(), (int)topRight.getY(),2,2);
      img.drawOval ((int)bottomLeft.getX(),(int) bottomLeft.getY(),2,2);
      img.drawOval ((int)bottomRight.getX(), (int)bottomRight.getY(),2,2);*/
      if(s.shields[0]!=0)
      {
        img.setColor(new Color(0,(int)(2.55*s.shields[0]),0));
        img.drawLine(topLeft.x, topLeft.y,bottomLeft.x, bottomLeft.y);
      }
      
      if(s.shields[1]!=0)
      {
        img.setColor(new Color(0,(int)(2.55*s.shields[1]),0));
        img.drawLine(topRight.x,topRight.y,bottomRight.x,bottomRight.y);
      }
      
      if(s.shields[2]!=0)
      {
        img.setColor(new Color(0,(int)(2.55*s.shields[2]),0));
        img.drawLine(topRight.x,topRight.y,topLeft.x,topLeft.y);
      }
      
      if(s.shields[3]!=0)
      {
        img.setColor(new Color(0,(int)(2.55*s.shields[3]),0));
        img.drawLine(bottomRight.x,bottomRight.y,bottomLeft.x,bottomLeft.y);
      }
      //////////////////////////////*/
    }
    img.setColor(Color.yellow);
    try
    {
      //if (playerShip.battery>10)
        //img2.drawLine((int)phaser.phaser.getX1(),(int) phaser.phaser.getY1(),(int)phaser.phaser.getX2(),(int)phaser.phaser.getY2());
      for (Phaser p:phasers)
      {
        img2.drawLine((int)p.line.getX1(),(int) p.line.getY1(),(int)p.line.getX2(),(int)p.line.getY2());
      }
      /*for(Line2D.Double line:checkPhaser.enemyFire)
      {
        img2.drawLine((int)line.getX1(),(int) line.getY1(),(int)line.getX2(),(int)line.getY2());
      }*/
    }
    catch (Exception e)
    {
    }

    Graphics2D g2 = (Graphics2D)g;
    g2.drawImage(buffer,0,0,null);
    try
    {
      Thread.sleep(10);
    }
    catch(Exception e)
    {
    }
    repaint();
  }
  
  public void controls()
  {
    if (up)
    {
      playerShip.speed+=0.1;
    }
    if (down)
    {
      playerShip.speed-=0.1;
    }
    if (left)
      playerShip.angle+=0.05;
    if (right)
      playerShip.angle-=0.05;
  }
  
  public static void main(String[]args)
  {
    try
    {
      ships=4-Integer.parseInt(args[0]);
    }
    catch(Exception e)
    {
    }
    new GameWindow();
  }
}